/**
 * 
 */
package baduga.server;

import java.io.IOException;
import java.net.ServerSocket;

import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;

import baduga.core.Core_Exception;
import baduga.core.Core_JsonDataSchema;
import baduga.core.Core_Messages;
import baduga.core.Core_Network_Api;

/**
 * @author Janek
 *
 */
public class  Network_Api extends Core_Network_Api {
	
	
	/** ilość socketów na serwerze */
	private int countSocket = 0;

	
	/** ServerSocker */
    private SSLServerSocketFactory sslSocketFactory = null;
    private ServerSocket serverSocketSSL = null;
    
    /** ClientSocket */
    private SSLSocket clientSocketSSL = null;
    
    /** ClientThread */
    private Network_API__Client_Thread clientThread = null;
    private Network_API__Client_Thread clientThreadDeb  = new Network_API__Client_Thread(null, true);
    
    
    /** Statusy serwera 
     * 0 - Globalny
     * 1 - Nasłuchu
     * 
     * */
    private static boolean serverStatus[] = new boolean[2];

    /**
     * Konstruktor
     */
    Network_Api()
    {
    	setUP();
    }
	
    
    
    /**
     * Ta funkcja konfigurje serwer
     */
    public final void setUP()
    {
    	this.passwords[0] = "#a0d9$a%0B0)_";
    	this.passwords[1] = "QpW--@0S(Wc#a";

    	/**  Poprawa ściezki */
    	this.dataCerts[1] +="_srv.p12";
    	
    	/** debug SSL-a */
    	Network_Api.sslDebug = true;
    	
    	/** Ustawienia dla serwera */
		System.setProperty("javax.net.ssl.keyStoreType", 	"pkcs12");
		System.setProperty("javax.net.ssl.trustStoreType", 	"jks");
		System.setProperty("javax.net.ssl.keyStore", this.dataCerts[0] + this.dataCerts[1] );
		System.setProperty("javax.net.ssl.trustStore", this.dataCerts[0] + this.dataCerts[2]  );
		System.setProperty("javax.net.debug", "ssl");
		System.setProperty("javax.net.ssl.keyStorePassword", this.passwords[0]);
		System.setProperty("javax.net.ssl.trustStorePassword", this.passwords[1]);
    	
    	
		
		sslSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
    }
    
	
	
	/**
	 * Zwraca informacje czy łączący sie gracz nie przekroczył limitu miejsc :(
	 * @return
	 */
	public boolean  checkSocketLimit()
	{
		boolean opStatus;

		if(countSocket + 1 > Game_Cfg.SOCKET_MAX)
		{
			opStatus = false;
		}
		else
		{
			opStatus = true;
		}
		
		return opStatus;
	}
	
	
	@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
	/**
	 * Funkcja tworzy sockety Servera 
	 * @return
	 */
	public boolean createServer()
	{
		boolean opStatus;

		try {

			serverSocketSSL = sslSocketFactory.createServerSocket(Game_Cfg.DEFAULT_PORT);
			opStatus = true;

		} catch (IOException e) {
			// TODO Auto-generated catch block
			opStatus = false;
		}
		
		
		return opStatus;
	}
	
	
	/**
	 * Funkcja inicjalizuje server & aktywuje nasłuch
	 */
	public void init()
	{
		serverStatus[0] = createServer();
		
		if(serverStatus[0])
		{
			/** Ustawienie statusu nasłuchu*/
			serverStatus[1] = true;
			
			
			
			while(serverStatus[1])
			{
				/** Obsługa klienta*/
				try {
					clientSocketSSL = (SSLSocket) serverSocketSSL.accept();

					/** Sprawdzenie limitu socketów */
					if(checkSocketLimit())
					{
						//Zwiększenie ilości socketów
						countSocket += 1;
						
						
						clientThread = new Network_API__Client_Thread(clientSocketSSL);
						
						/** Konfiguracja & inicjalizacja */
						clientThread.setDaemon(true);
						clientThread.start();
					}
					else
					{
						
						//Przepisanie socketa
						clientThreadDeb.setSocket(clientSocketSSL);
						
						//Wysłanie wiadomości
						clientThreadDeb.sendData(constructMessage(0x027B));
						
						//Zamknięcie
						clientThreadDeb.shutDown(false);
						
						
						//Wysłanie informacji o braku miejsc do klienta
						Core_Exception.showOwnMessage(Core_Messages.getMessage(0x027C), Core_Messages.getMessage(0x0100));
					}
					
					
				} catch (IOException e) {
					Core_Exception.showOwnMessage(Core_Messages.getMessage(0x027D), Core_Messages.getMessage(0x0100));
				}
			}
		}
		else
		{			
			Core_Exception.showOwnMessage(Core_Messages.getMessage(0x027F) + Integer.toString(Game_Cfg.DEFAULT_PORT) + Core_Messages.getMessage(0x0280), Core_Messages.getMessage(0x0100));
		}

		
		
	}
	
	
	/**
	 * Funkcja konstruje wiadomość
	 * 
	 * @param msgID
	 */
	public Core_JsonDataSchema constructMessage(int msgID)
	{
		//Def.
		Core_JsonDataSchema rData;
		
		//Inicjalizacja
		rData = new Core_JsonDataSchema(01, new int[] {
			0
		},
			new Object[] {
				msgID
		}, 
		null);
		
		
		
		return rData;
	}
	
	
	
	

}
